#ifndef GA_H
#define GA_H

#include <cmath>
#include <vector>
#include <algorithm>
#include "omp.h"
#include <io.h>
#include "game.h"
#include "ann.h"

using std::vector;
using std::sort;

#include "./parameter.h"

class Ga {
public:
struct Snake {
    float score, game_time, ann_time, final_score;
    int age;
    Ann ann;

    Snake() : score(0.0f), game_time(0.0f), ann_time(0.0f), final_score(0.0f),
        age(0), ann(ANN_TIMEOUT) {}
    Snake(int cell_num, int edge_num) : score(0.0f), game_time(0.0f), ann_time(0.0f), final_score(0.0f),
        age(0), ann(cell_num, edge_num, 32, 4, ANN_TIMEOUT) {}
    Snake(const char *filename) : score(0.0f), game_time(0.0f), ann_time(0.0f), final_score(0.0f),
        age(0), ann(filename, ANN_TIMEOUT) {}

    inline void updateFinalScore() {
        final_score = score;
        // final_score = score / (game_time * 0.01f + 1);
    }

    bool operator<(const Snake &b) const {
        return final_score > b.final_score;
    }
};

public:
int t;
vector<Snake*> snakes;

private:
// 繁殖
void reprodece(int id);
void reproduceAll(int num);
// 淘汰
void eliminateAll(int num);
// 计算个体适应度
void evaluate(Snake *snake);
void evaluateAll();

public:
Ga(int cell_num, int edge_num);
Ga(const char *filename);

// 迭代一次
void next();

void saveAllParam(const char *filename);

inline float getAvgScore() {
    float total_score = 0;
    for (int i = 0; i < POPULATION_NUM; i++)
        total_score += snakes[i]->score;
    return total_score / POPULATION_NUM;
}

};

#include "ga.cpp"

#endif